package com.fullstack.server.endpoints

import cats.*
import cats.implicits.*
import com.fullstack.common.domain.error.*
import com.fullstack.server.util.TokenUtil
import io.circe.generic.auto.*
import sttp.model.StatusCode
import sttp.tapir.*
import sttp.tapir.generic.auto.*
import sttp.tapir.json.circe.*
import sttp.tapir.server.PartialServerEndpoint

trait BaseEndpoint[F[_]: Applicative]:
  // here we are defining an error output, but the same can be done for regular outputs
  protected val baseEndpoint = endpoint.in("api")
    .errorOut(
      oneOf[ErrorInfo](
        oneOfVariant(statusCode(StatusCode.NotFound).and(jsonBody[NotFound].description("not found"))),
        oneOfVariant(statusCode(StatusCode.Unauthorized).and(jsonBody[Unauthorized].description("unauthorized"))),
        oneOfVariant(statusCode(StatusCode.NoContent).and(emptyOutputAs(NoContent))),
        oneOfDefaultVariant(jsonBody[Unknown].description("unknown"))
      )
    )

  // 需要验证的接口
  protected val authEndpoint: PartialServerEndpoint[String, String, Unit, ErrorInfo, Unit, Any, F] = baseEndpoint
    .securityIn(auth.bearer[String]())
    .serverSecurityLogic(TokenUtil.parseToken(_).pure[F])